package com.baymax.study.redisson.infrastructure.locks.utils;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson2.JSON;
import com.baymax.study.redisson.infrastructure.locks.framework.DistributedReadWriteLock;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;

import java.util.Arrays;

public class GlobalLockUtils {
    private static DistributedReadWriteLock distributedReadWriteLock;

    public static boolean checkIsLocked(String lockName, Object key, boolean isWriteLock) {
        if (isWriteLock) {
            return getReadWriteLock().getWriteLock().isLocked(buildLockValue(lockName, key));
        } else {
            return getReadWriteLock().getReadLock().isLocked(buildLockValue(lockName, key));
        }
    }

    public static DistributedReadWriteLock getReadWriteLock() {
        if (distributedReadWriteLock == null) {
            distributedReadWriteLock = SpringUtil.getBean(DistributedReadWriteLock.class);
        }
        return GlobalLockUtils.distributedReadWriteLock;
    }

    public static String buildLockValue(String lockName, Object key) {
        String keys = "";
        if (key != null) {
            if (isWrapClass(key.getClass())) {
                keys = String.valueOf(key);
            } else {
                keys = JSON.toJSONString(key);
            }
        }
        String data = lockName + keys;
        if (data.length() > 260) {
            data = SecureUtil.sha256(data);
        }
        return "global_lock_" + data;
    }

    public static String sort(String s) {
        // 先将字符传转为 char 型数组
        char[] chars = s.toCharArray();
        // 使用 Arrays.sort(chars) 方法进行排序
        Arrays.sort(chars);
        // 然后再将char型数组作为参数传递给String类构造器
        String sortStr = new String(chars);
        // 返回排序好的字符串
        return sortStr;
    }

    public static boolean isWrapClass(Class clz) {
        try {
            boolean primitive = clz.isPrimitive();
            if (primitive) {
                return true;
            }
            Class[] clazz = {Integer.class, String.class, Double.class, Float.class, Long.class, Byte.class, Boolean.class, Short.class};
            return Arrays.stream(clazz).anyMatch(clz::isAssignableFrom);
        } catch (Exception e) {
            return false;
        }
    }
}
